#include "files/file.h"
#include "scanner/multi_part_filter.h"
#include "settings/settings.h"

#include <algorithm>

namespace Tvimeg
{
	class IsMultiPart
	{
	public:
		IsMultiPart(const std::string& file1_in, const std::string& file2_in, std::size_t& commonNameLengthIn)
			:	file1(file1_in), file2(file2_in), commonNameLength(commonNameLengthIn)
		{
		}

		bool operator()(const std::string& multiPartString)
		{
			// get some lengths
			const std::size_t multiPartLength = multiPartString.length();
			const std::size_t file1Length = file1.length();
			const std::size_t file1PreLength = file1Length - multiPartLength;
			const std::size_t file2Length = file2.length();

			// the file name has to be longer than the multi part string
			// and the second file name has to be longer than the first minus the multi part string
			if (file1Length > multiPartLength && file2Length > file1PreLength)
			{
				// check if the file name ends with the multi part string
				if (file1.compare(file1PreLength, multiPartLength, multiPartString) == 0)
				{
					// check if the file1 name before the multi part string matches the start of file2 name
					if (file1.compare(0, file1PreLength, file2, 0, file1PreLength) == 0)
					{
						// check if the remaining part of file2 is also a multi part string
						if (IsMultiPartString(file2.substr(file1PreLength)))
						{
							commonNameLength = file1PreLength;
							return true;
						}
					}
				}
			}

			return false;
		}

	private:
		static bool IsMultiPartString(const std::string& string)
		{
			// just check if the string is in the list of supported multi part strings
			return std::find(Settings::GetInstance().MultiPartsBegin(), Settings::GetInstance().MultiPartsEnd(), string) != Settings::GetInstance().MultiPartsEnd();
		}

		const std::string&	file1;
		const std::string&	file2;

		std::size_t&		commonNameLength;
	};

	MultiPartFilter::MultiPartFilter(const File& file, std::size_t& commonNameLengthIn)
		:	fileName(GetLowerCaseFileName(file)), commonNameLength(commonNameLengthIn)
	{
	}

	std::string MultiPartFilter::GetLowerCaseFileName(const File& file)
	{
		std::string fileName(file.GetName());
		std::transform(fileName.begin(), fileName.end(), fileName.begin(), tolower);
		return fileName;
	}

	bool MultiPartFilter::operator ()(const File& file)
	{
		// get the lower case file name of the other file
		const std::string otherFileName = GetLowerCaseFileName(file);

		// use the supported multi part strings to check if these two files are part of a multi part movie
		const Settings::StringIterator end = Settings::GetInstance().MultiPartsEnd();
		return std::find_if(Settings::GetInstance().MultiPartsBegin(), end, IsMultiPart(fileName, otherFileName, commonNameLength)) != end;
	}
}
